﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Alexinea.Autofac.Extensions.DependencyInjection;
using Autofac;
using AutoMapper;
using BestTrader.Cms.Core;
using BestTrader.Cms.Core.Options;
using BestTrader.Cms.Repository.SqlServer;
using BestTrader.Cms.RmmfSoftServices;
using BestTrader.Cms.Services;
using BestTrader.Cms.WebApi.Common;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Swashbuckle.AspNetCore.Swagger;
using NLog.Extensions.Logging;


namespace BestTrader.Cms.WebApi
{
    public class Startup
    {
        //Cors policy name
        private const string _defaultCorsPolicyName = "BestTraderCors";

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            #region Config

            services.Configure<DbOption>("BT.TEST", Configuration.GetSection("DbOption"));
            services.Configure<QiniuOption>("QINIU", Configuration.GetSection("QiniuOption"));
            services.Configure<SystemBankOption>("SYS.BANK", Configuration.GetSection("SystemBankOption"));
            services.Configure<YunpayOption>("YUNPAY", Configuration.GetSection("YunpayOption"));
            services.Configure<GomePayOption>("GOMEPAY", Configuration.GetSection("GomePayOption"));
            services.Configure<RmmsoftOption>("RMMSOFT", Configuration.GetSection("RmmsoftOption"));

            #endregion

            #region Configure Jwt Authentication

            services.AddAuthentication(s =>
            {
                s.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                s.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(s =>
            {
                s.TokenValidationParameters = new TokenValidationParameters
                {
                    //NameClaimType = JwtClaimTypes.
                    //ValidIssuer = "yuiter.com",
                    //ValidAudience = "yuiter.com",
                    //IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecurityKey"])),
                     ValidateIssuer = true,//是否验证Issuer
                    ValidateAudience = true,//是否验证Audience
                    ValidateLifetime = true,//是否验证失效时间
                    ValidateIssuerSigningKey = true,//是否验证SecurityKey
                    ValidAudience = Configuration["Jwt:Audience"],//Audience
                    ValidIssuer = Configuration["Jwt:Issuer"],//Issuer，这两项和前面签发jwt的设置一致
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecurityKey"]))//拿到SecurityKey

                };
            });

            #endregion

            services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
                .AddFluentValidation(fv =>
                {
                    //fv.RegisterValidatorsFromAssemblyContaining<ManagerRoleValidation>();
                    fv.RunDefaultMvcValidationAfterFluentValidationExecutes = false;
                }); ;
            //services.AddMvc(
            //    options => options.Filters.Add(new CorsAuthorizationFilterFactory(_defaultCorsPolicyName))
            //).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            services.AddAutoMapper();

            //services.AddMiniProfiler(options =>
            //    options.RouteBasePath = "/profiler"
            //);

            #region Configure Cors

            services.AddCors(options => options.AddPolicy(_defaultCorsPolicyName,
                cors => cors.WithOrigins(
                        Configuration["Application:CorsOrigins"]
                        .Split(",", StringSplitOptions.RemoveEmptyEntries).ToArray()
                    )
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials()));

            #endregion

            #region Configure API Version

            services.AddApiVersioning(o =>
            {
                o.ReportApiVersions = true;//return versions in a response header
                o.DefaultApiVersion = new ApiVersion(1, 0);//default version select 
                o.AssumeDefaultVersionWhenUnspecified = true;//if not specifying an api version,show the default version
            });

            #endregion

            services.InitSwagger();

            #region HttpClient
            // [.NET Core 中正确使用 HttpClient 的姿势](https://www.cnblogs.com/willick/p/net-core-httpclient.html)
            var rmmsoftOpt = Configuration.GetSection("RmmsoftOption").Get<RmmsoftOption>();
            services.AddHttpClient(Constants.HTTP_RMMSOFT, x =>
            {
                x.BaseAddress = new Uri(rmmsoftOpt.BaseUrl);
                x.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
            });
            services.AddHttpClient<YunPayClientService>();
            services.AddHttpClient<GomePayClientService>();
            #endregion

            #region AutoFac
            //[Autofac 使用经验](https://www.cnblogs.com/ideacore/p/7532041.html)
            var builder = new ContainerBuilder();
            builder.Populate(services);
            builder.RegisterAssemblyTypes(typeof(ManagerRoleRepository).Assembly)
                   .Where(t => t.Name.EndsWith("Repository"))
                   .InstancePerLifetimeScope()
                   .AsImplementedInterfaces();
            builder.RegisterAssemblyTypes(typeof(ManagerRoleService).Assembly)
                 .Where(t => t.Name.EndsWith("Service"))
                 .InstancePerLifetimeScope()
                 .AsImplementedInterfaces();
            builder.RegisterAssemblyTypes(typeof(RmmfSoftAccountService).Assembly)
                .InstancePerLifetimeScope()
                .Where(t => t.Name.EndsWith("Service"));

            return new AutofacServiceProvider(builder.Build());

            #endregion

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                //app.UseDatabaseErrorPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            ////Enable Cors
            app.UseCors(_defaultCorsPolicyName);

            ////Enable Authentication
            app.UseAuthentication();    //启用验证

            app.UseMiniProfiler();

            app.UseHttpsRedirection();
            app.UseMvc();

            //add NLog to ASP.NET Core
            loggerFactory.AddNLog();

            app.UseStaticFiles(new StaticFileOptions
            {
                //FileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory()),
                //设置不限制content-type 该设置可以下载所有类型的文件，但是不建议这么设置，因为不安全
                //下面设置可以下载apk和nupkg类型的文件
                ContentTypeProvider = new FileExtensionContentTypeProvider(new Dictionary<string, string>
                {
                      { ".apk", "application/vnd.android.package-archive" },
                      { ".css", "text/css" },
                      { ".jpe", "image/jpeg" },
                      { ".jpeg", "image/jpeg" },
                      { ".jpg", "image/jpeg" },
                      { ".js", "application/javascript" },
                      { ".doc", "application/msword" },
                      { ".docm", "application/vnd.ms-word.document.macroEnabled.12" },
                      { ".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document" },
                      { ".xml", "text/xml" }

                })
            });
            app.ConfigureSwagger();
        }
    }
}
